#pragma once
#ifndef TUVOK_BVR_DATASET_H
#define TUVOK_BVR_DATASET_H

#include <vector>
#include "../FileBackedDataset.h"

namespace tuvok {

class BVRDataset : public FileBackedDataset {
public:
  // NO: BVRDataset(const std::string& strFilename, UINT64 iMaxAcceptableBricksize, bool bVerify, bool bMustBeSameVersion = true);
  BVRDataset();
  virtual ~BVRDataset();

  // Brick Data
  virtual UINTVECTOR3 GetBrickVoxelCounts(const BrickKey&) const;
  virtual bool GetBrick(const BrickKey&, std::vector<boost::uint8_t>&) const;
  virtual bool GetBrick(const BrickKey&, std::vector<boost::int8_t>&) const;
  virtual bool GetBrick(const BrickKey&, std::vector<boost::uint16_t>&) const;
  virtual bool GetBrick(const BrickKey&, std::vector<boost::int16_t>&) const;
  virtual bool GetBrick(const BrickKey&, std::vector<boost::uint32_t>&) const;
  virtual bool GetBrick(const BrickKey&, std::vector<boost::int32_t>&) const;
  virtual bool GetBrick(const BrickKey&, std::vector<float>&) const;
  virtual bool GetBrick(const BrickKey&, std::vector<double>&) const;
  virtual UINT64VECTOR3 GetEffectiveBrickSize(const BrickKey &) const;

  /// Acceleration queries.
  virtual bool ContainsData(const BrickKey &k, double isoval) const;
  virtual bool ContainsData(const BrickKey &k, double fMin,double fMax) const;
  virtual bool ContainsData(const BrickKey &k, double fMin,double fMax, double fMinGradient,double fMaxGradient) const;

  // LOD Data
  /// @todo fixme -- this should take a brick key and just ignore the spatial
  /// indices.
  ///@{
  virtual BrickTable::size_type GetBrickCount(size_t lod, size_t ts) const;
  virtual UINT64VECTOR3 GetDomainSize(const size_t lod=0, const size_t ts=0) const;
  ///@}
  virtual UINT64 GetNumberOfTimesteps() const;

  // Global Data
  float MaxGradientMagnitude() const;
  // NO: virtual UINTVECTOR3 GetMaxBrickSize() const;
  // NO: virtual UINT64VECTOR3 GetMaxUsedBrickSizes() const;
  virtual UINTVECTOR3 GetBrickOverlapSize() const;
  virtual UINT64 GetLODLevelCount() const;
  virtual UINT64 GetBitWidth() const;
  virtual UINT64 GetComponentCount() const;
  virtual bool GetIsSigned() const;
  virtual bool GetIsFloat() const;
  virtual bool IsSameEndianness() const;
  virtual std::pair<double,double> GetRange() const;
  // computes the range and caches it internally for the next call to
  // 'GetRange'.
  // NO: void ComputeRange();

  // Global "Operations" and additional data not from the BVR file
  virtual bool Export(UINT64 iLODLevel, const std::string& targetFilename,
                      bool bAppend,
                      bool (*brickFunc)(LargeRAWFile* pSourceFile,
                                        const std::vector<UINT64> vBrickSize,
                                        const std::vector<UINT64> vBrickOffset,
                                        void* pUserContext) = NULL,
                      void *pUserContext = NULL,
                      UINT64 iOverlap=0) const;

  virtual const std::vector<std::pair<std::string, std::string> > GetMetadata() const;

  virtual bool SaveRescaleFactors();
  // NO: bool AppendMesh(Mesh* m);
  // NO: bool RemoveMesh(size_t iMeshIndex);
  // NO: bool GeometryTransformToFile(size_t iMeshIndex, const FLOATMATRIX4& m);

  // FileBackedDataset
  virtual bool CanRead(const std::string&, const std::vector<int8_t>&) const;
  virtual bool Verify(const std::string&) const;
  virtual FileBackedDataset* Create(const std::string&, UINT64, bool) const;
  virtual std::list<std::string> Extensions() const;
  // NO: const BVR* GetBVRFile() const {return m_pDatasetFile;}

  virtual const char* Name() const { 
      return "Generic BVR Dataset"; 
  }

  // NO: NDBrickKey IndexToVectorKey(const BrickKey &k) const;

private:
  // NO: std::vector<UINT64> IndexToVector(const BrickKey &k) const;
  // NO: bool Open(bool bVerify, bool bReadWrite, bool bMustBeSameVersion=true);
  // NO: void Close();
  // NO: void FindSuitableRasterBlocks();
  // NO: void ComputeMetaData(size_t ts);
  // NO: void GetHistograms(size_t ts);

  // NO: void FixOverlap(UINT64& v, UINT64 brickIndex, UINT64 maxindex, UINT64 overlap) const;

  // NO: size_t DetermineNumberOfTimesteps();
  // NO: bool VerifyRasterDataBlock(const RasterDataBlock*) const;

private:
 // struct Timestep {
	//Timestep() : m_fMaxGradMagnitude(0), m_pVolumeDataBlock(NULL),
	//			 m_pHist1DDataBlock(NULL), m_pHist2DDataBlock(NULL), 
	//			 m_pMaxMinData(NULL) {}
 //   /// used for 2D TF scaling
 //   float                        m_fMaxGradMagnitude;
 //   const RasterDataBlock*       m_pVolumeDataBlock; ///< data
 //   const Histogram1DDataBlock*  m_pHist1DDataBlock;
 //   const Histogram2DDataBlock*  m_pHist2DDataBlock;
 //   MaxMinDataBlock*             m_pMaxMinData;      ///< acceleration info

 //   /// number of voxels of overlap with neighboring bricks
 //   UINTVECTOR3                  m_aOverlap;
 //   /// size of the domain for this timestep (i.e. n_voxels in finest LOD)
 //   std::vector<UINT64VECTOR3>   m_aDomainSize;
 //   /// max values for logical brick indices; std::vector index gives LOD.
 //   std::vector<UINT64VECTOR3>   m_vaBrickCount;
 //   /// the size of each individual brick.  Slowest moving dimension is LOD;
 //   /// then x,y,z.
 //   std::vector<std::vector<std::vector<std::vector<UINT64VECTOR3> > > >  m_vvaBrickSize;
 //   /// same layout as m_vvaBrickSize, but gives acceleration min/max info.
 //   std::vector<std::vector<std::vector<std::vector<InternalMaxMinElement> > > > m_vvaMaxMin;
 //   size_t                       block_number;
 // };
 // std::vector<Timestep>        m_timesteps;
  //std::vector<GeometryDataBlock*> m_TriSoupBlocks;
  //const KeyValuePairDataBlock* m_pKVDataBlock;
  //UINTVECTOR3                  m_aMaxBrickSize;
  //bool                         m_bIsSameEndianness;

  //BVR*                         m_pDatasetFile;
  //std::pair<double,double>     m_CachedRange;

  //UINT64                       m_iMaxAcceptableBricksize;
};

}

#endif // TUVOK_BVR_DATASET_H
